package com.pi.shisan.service.service.impl;

import com.alibaba.fastjson2.JSON;
import com.pi.shisan.service.constants.HttpHeadVal;
import com.pi.shisan.service.domain.WeatherCity;
import com.pi.shisan.service.dto.CityDTO;
import com.pi.shisan.service.dto.WeatherInfoDTO;
import com.pi.shisan.service.dto.from.CurrentWeatherDTO;
import com.pi.shisan.service.dto.from.FutureWeatherListDTO;
import com.pi.shisan.service.mapper.MyWeatherCityMapper;
import com.pi.shisan.service.mapper.WeatherCityMapper;
import com.pi.shisan.service.service.WeatherService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

@Service
public class WeatherServiceImpl implements WeatherService {

    @Autowired
    private HttpClient httpClient;

    @Autowired
    private WeatherCityMapper weatherCityMapper;

    @Autowired
    private MyWeatherCityMapper myWeatherCityMapper;

    private volatile WeatherInfoDTO cache;

    private LocalDateTime lastUpdate;

    private LocalDateTime convertNow() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime curr = LocalDateTime.of(now.toLocalDate(), LocalTime.of(now.getHour(), now.getMinute() > 30 ? 0 : 30, 0));
        if (now.getMinute() > 30) {
            curr = curr.plusHours(1);
        }
        return curr;
    }

    @Override
    public WeatherInfoDTO getWeatherInfo() throws Exception{
        if (cache == null) {
            cache = forceGetWeatherInfo();
            lastUpdate = convertNow();
        } else {
            LocalDateTime last = this.lastUpdate;
            if (System.currentTimeMillis() - last.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() > 1800000) {
                cache = forceGetWeatherInfo();
                this.lastUpdate = convertNow();
            }
        }
        final WeatherInfoDTO cache = this.cache;
        if (cache == null) {
            return null;
        }
        WeatherInfoDTO w = new WeatherInfoDTO();
        w.setMin(cache.getMin());
        w.setMax(cache.getMax());
        w.setTemp(cache.getTemp());
        w.setStatus(cache.getStatus());

        CityDTO cityDTO = new CityDTO();
        cityDTO.setId(cache.getCityInfo().getId());
        cityDTO.setName1(cache.getCityInfo().getName1());
        cityDTO.setName2(cache.getCityInfo().getName2());
        cityDTO.setName3(cache.getCityInfo().getName3());
        w.setCityInfo(cityDTO);
        return w;
    }

    @Override
    public WeatherInfoDTO forceGetWeatherInfo() throws Exception{
        Long recordId = myWeatherCityMapper.selectMyCityRecordId();
        if (recordId != null) {
            WeatherCity weatherCity = weatherCityMapper.selectById(recordId);
            if (weatherCity != null && StringUtils.isNotBlank(weatherCity.getCityId())) {
                long timestamp = System.currentTimeMillis();
                String cityId = weatherCity.getCityId();
                FutureWeatherListDTO weatherList = JSON.parseObject(readJsonFromWeatherCom("https://d1.weather.com.cn/wap40/"+cityId+".html?_=" + timestamp), FutureWeatherListDTO.class);
                if (weatherList.getDatas() != null && weatherList.getDatas().size() > 0) {
                    FutureWeatherListDTO.WeatherInfo today = weatherList.getDatas().get(0);
                    CurrentWeatherDTO currentWeather = JSON.parseObject(readJsonFromWeatherCom("https://d1.weather.com.cn/sk_2d/"+cityId+".html?_=" + timestamp), CurrentWeatherDTO.class);
                    WeatherInfoDTO result = new WeatherInfoDTO();
                    result.setMax(today.getMax());
                    result.setMin(today.getMin());
                    result.setTemp(currentWeather.getTemp());
                    result.setStatus(currentWeather.getWeather());
                    CityDTO cityDTO = new CityDTO();
                    cityDTO.setId(weatherCity.getId());
                    cityDTO.setName1(weatherCity.getName1());
                    cityDTO.setName2(weatherCity.getName2());
                    cityDTO.setName3(weatherCity.getName3());
                    result.setCityInfo(cityDTO);
                    this.cache = result;
                    return result;
                }
            }
        }
        this.cache = null;
        return null;
    }

    public String readJsonFromWeatherCom(String url) throws Exception{
        //24小时天气预报（多云？温度？），以小时为单位排列的列表 jf: 小时  jb:温度
        //https://d1.weather.com.cn/wap_40d/101210106.html?_=1652186737431
        //取当前温度
        //"https://d1.weather.com.cn/sk_2d/101210107.html?_="+System.currentTimeMillis()
        //未来40天天气预报取第一条今天，今日温度区间
        //https://d1.weather.com.cn/wap40/101210107.html?_=1651642867870
        HttpGet get = new HttpGet(url);
        get.setHeader("Host", "d1.weather.com.cn");
        get.setHeader("Referer", "http://m.weather.com.cn/");
        get.setHeader("Sec-Fetch-Dest", "script");
        get.setHeader("Sec-Fetch-Mode", "no-cors");
        get.setHeader("Sec-Fetch-Site", "cross-site");
        get.setHeader("sec-ch-ua-mobile", "?0");
        get.setHeader("sec-ch-ua-platform", "Android");
        get.setHeader("sec-ch-ua", " Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\", \"Microsoft Edge\";v=\"101");
        get.setHeader(HttpHeaders.USER_AGENT, HttpHeadVal.USER_AGENT_VAL);
        HttpResponse response = httpClient.execute(get);
        try {
            if (response.getStatusLine().getStatusCode() == 200) {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                response.getEntity().writeTo(bos);
                //temp 当前温度
                //weather 天气状况描述
                String json = new String(bos.toByteArray(), StandardCharsets.UTF_8);
                int index;
                if (json != null && (index = json.indexOf("=")) > -1) {
                    json = json.substring(index + 1);
                }
                return json;
            } else {
                throw new RuntimeException("返回："+response.getStatusLine().getStatusCode());
            }
        } finally {
            EntityUtils.consume(response.getEntity());
        }
    }

}
